﻿using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using WxLib.Core.Util;
using WxLib.Core.Serializers;
using WxLib.Core.RequestHandlers;
using WxLib.Common;
using WxLib.Business;
using WxLib.QRCode;
using wxLib.QRCode.Models;
using WxLib.Sns;
using System.Diagnostics.Contracts;


namespace wxLib.QRCode
{
    /// <summary>
    /// 小程序
    /// </summary>
    public class WxXcxQRCode
    {

        private string appid = "wx70fff8d82d14aaef";
        private string secret = "db3a190d61d748f025c2ae0cfb22e860";

        /// <summary>
        /// 获取或设置用于执行请求的RequestHandler
        /// </summary>
        public IPostRequestHandler RequestHandler;

        public IRequestHandler ReHandler;

        /// <summary>
        /// 构造函数
        /// </summary>
        public WxXcxQRCode()
        {
            RequestHandler = new RequestHandler(new JsonSerializer());
            ReHandler = new RequestHandler(new JsonSerializer());
        }

        /// <summary>
        /// code 换取 session_key
        /// </summary>
        /// <param name="loginCode"></param>
        /// <returns></returns>
        public async Task<Code2SessionResponse> GetJsCode2SessionAsync(string loginCode)
        {
            Contract.Requires(loginCode != null, "logincode cannot be null.");
            string relUri = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + loginCode + "&grant_type=authorization_code";
            return await RequestHandler.RequestAsync<Code2SessionResponse>(new Uri(relUri));
        }

        /// <summary>
        /// 解密会员数据
        /// </summary>
        /// <param name="sessionkey"></param> 
        /// <param name="encryptedData"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        public PhoneNumberResponse BindUserInformation(CreateUserDto dto)
        {
            return WXBizDataCrypt.Decrypt<PhoneNumberResponse>(dto.encryptedData, dto.iv, dto.sessionkey);
        }


        


        /// <summary>
        /// 生成带参数的小程序二维码
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="type">0：返回地址 1：绝对路径 +base64</param>
        /// <returns></returns>
        public Tuple<string, byte[], string> CreateWXAQRCode(string path, int type)
        {
            WxAccessTokenResponse response = WxCommonApi.Instance().GetAccessTokenXcx(appid, secret);
            var relUri = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=" + response.access_token;
            string jsonStr = "{\"access_token\":\"" + response.access_token + "\",\"path\":\"" + path + "\"}";
            var tup = PostMoths(relUri, jsonStr);
            if (type == 0)
                return new Tuple<string, byte[], string>(tup.Item1, null, "");
            else
            {
                return new Tuple<string, byte[], string>(tup.Item2, tup.Item3, tup.Item4);
            }
        }

        /// <summary>
        /// 生成带参数的小程序二维码
        /// </summary>
        /// <param name="page">路径</param>
        /// <param name="scene">参数</param>
        /// <param name="type">0：返回地址 1：绝对路径 +base64</param>
        /// <returns></returns>
        public Tuple<string, byte[], string> getWXACodeUnlimit(string page, string scene, int type)
        {
            WxAccessTokenResponse response = WxCommonApi.Instance().GetAccessToken(appid, secret);
            var relUri = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + response.access_token;
            string jsonStr = "{\"access_token\":\"" + response.access_token + "\",\"scene\":\"" + scene + "\",\"page\":\"" + page + "\"}";


            string DataJson = "{";
            DataJson += string.Format("\"scene\":\"{0}\",", scene);//所要传的参数用,分看
            //DataJson += string.Format("\"width\":\"{0}\",", 124);
            DataJson += string.Format("\"page\":\"{0}\"", page);//扫码所要跳转的地址，根路径前不要填加'/',不能携带参数（参数请放在scene字段里），如果不填写这个字段，默认跳主页面
            //DataJson += "\"line_color\":{";
            //DataJson += string.Format("\"r\":\"{0}\",", "0");
            //DataJson += string.Format("\"g\":\"{0}\",", "0");
            //DataJson += string.Format("\"b\":\"{0}\"", "0");
            //DataJson += "}";
            DataJson += "}";



            var tup = PostMoths(relUri, DataJson);
            if (type == 0)
                return new Tuple<string, byte[], string>(tup.Item1, null, "");
            else
            {
                return new Tuple<string, byte[], string>(tup.Item2, tup.Item3, tup.Item4);
            }
        }


        /// <summary>
        /// 图片路径|文件名称|base64|图片绝对路径
        /// </summary>
        /// <param name="url"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static Tuple<string, string, byte[], string> PostMoths(string url, string param)
        {
            string strURL = url;
            System.Net.HttpWebRequest request;
            request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(strURL);
            request.Method = "POST";
            request.ContentType = "application/json;charset=UTF-8";
            string paraUrlCoded = param;
            byte[] payload;
            payload = System.Text.Encoding.UTF8.GetBytes(paraUrlCoded);
            request.ContentLength = payload.Length;
            System.IO.Stream writer = request.GetRequestStream();
            writer.Write(payload, 0, payload.Length);
            writer.Close();
            System.Net.HttpWebResponse response;
            response = (System.Net.HttpWebResponse)request.GetResponse();
            System.IO.Stream s;
            s = response.GetResponseStream();//返回图片数据流
            byte[] tt = StreamToBytes(s);//将数据流转为byte[]

            //在文件名前面加上时间，以防重名
            string imgName = DateTime.Now.ToString("yyyyMMddhhmmss") + ".jpg";
            //文件存储相对于当前应用目录的虚拟目录
            string path = "/image/";
            //获取相对于应用的基目录,创建目录
            string imgPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"wwwroot\Upload") + path;     //通过此对象获取文件名

            System.IO.Directory.CreateDirectory(imgPath);

            System.IO.File.WriteAllBytes(imgPath + imgName, tt);//讲byte[]存储为图片
            return new Tuple<string, string, byte[], string>("/Upload/image/" + imgName, imgName, tt, imgPath + imgName);
        }

        ///将数据流转为byte[]
        public static byte[] StreamToBytes(System.IO.Stream stream)
        {
            System.Collections.Generic.List<byte> bytes = new System.Collections.Generic.List<byte>();
            int temp = stream.ReadByte();
            while (temp != -1)
            {
                bytes.Add((byte)temp);
                temp = stream.ReadByte();
            }
            return bytes.ToArray();
        }

    }
}
